package top.mingyi4cjh.cms.controller;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import top.mingyi4cjh.cms.common.error.BusinessException;
import top.mingyi4cjh.cms.common.error.EmBusinessError;
import top.mingyi4cjh.cms.common.response.CommonReturnType;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import static top.mingyi4cjh.cms.common.utils.Util.replaceStr;

/**
 * @author MingYi
 * @program cms
 * @create 2022/04/21 23:34
 */
public class BaseController {
    public static final String CONTENT_TYPE_FORMED = "application/x-www-form-urlencoded";
    public static final String CONTENT_TYPE_DATA ="multipart/form-data";
    public static final String UNKNOWN_VALUE = "unknown";

    public static final int MAX_USER_NAME_LENGTH = 20;
    public static final int MIN_USER_NAME_LENGTH = 6;

    private static final Pattern ILLEGAL_CHAR = Pattern.compile("[ `~!@#$%^&*()+=|{}':;,\\[\\].<>/?！￥…（）—【】‘；：”“’。，、？]|\n|\r|\t");


    Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public Object handlerException(Exception ex) {
        Map<String, Object> responseData = new HashMap<>(16);
        if (ex instanceof BusinessException) {
            BusinessException businessException = (BusinessException) ex;
            responseData.put("errCode", businessException.getErrCode());
            responseData.put("errMsg", businessException.getErrMsg());
        } else {
            responseData.put("errCode", EmBusinessError.UNKNOWN_ERROR.getErrCode());
            responseData.put("errMsg", EmBusinessError.UNKNOWN_ERROR.getErrMsg());
            logger.error("Exception INFO", ex);
        }
        return CommonReturnType.create(responseData, "fail");
    }

    /**
     * 获取一个request中记录的IP地址信息
     *
     * @param request 一次访问的HttpServletRequest
     * @return 源IP
     */
    public String getIpInformation(HttpServletRequest request) {
        String ip = null;
        //X-Forwarded-For：Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || UNKNOWN_VALUE.equalsIgnoreCase(ipAddresses)) {
            //Proxy-Client-IP：apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || UNKNOWN_VALUE.equalsIgnoreCase(ipAddresses)) {
            //WL-Proxy-Client-IP：weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || UNKNOWN_VALUE.equalsIgnoreCase(ipAddresses)) {
            //HTTP_CLIENT_IP：有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || UNKNOWN_VALUE.equalsIgnoreCase(ipAddresses)) {
            //X-Real-IP：nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }
        //有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }
        //还是不能获取到，最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || UNKNOWN_VALUE.equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }

        ip = replaceStr(ip);
        return ip;
    }

    /**
     * 检验一个string的合法性：
     * 长度>20或<6不合法;
     * 含有非法字符不合法;
     * 以_开头或结尾不合法;
     *
     * @param str 待检验的字符串
     * @return str的合法性
     */
    public boolean isLegalString(String str) {
        if (StringUtils.isEmpty(str) || str.length() < MIN_USER_NAME_LENGTH || str.length() > MAX_USER_NAME_LENGTH) {
            return false;
        }

        // 匹配不到特殊字符，且开头结尾不为_
        return !ILLEGAL_CHAR.matcher(str).find() && str.matches("^(?![_])([\\s\\S]*)(?<![_])$");
    }
}
